import ResLoader from "../cfw/res/ResLoader";
import { ResType } from "../cfw/res/ResInterface";
import ResItem from "../cfw/res/ResItem";
import { logError, logWarn, logInfo, DIR } from "../cfw/tools/Define";
import TSMap from "../cfw/struct/TSMap";
import ResHelper from "./ResHelper";

const { ccclass, property } = cc._decorator;

@ccclass
export default class DragonAnimation extends cc.Component {

    @property(cc.JsonAsset)
    config: cc.JsonAsset = null;

    @property(cc.Sprite)
    sprite: cc.Sprite = null;

    @property
    actoinName: string = ''

    @property
    configName: string = ''

    @property
    loop: boolean = true;


    protected frame: number = 0;
    protected dt: number = 0;
    protected frameData: any
    protected static loader: ResLoader = new ResLoader(new ResHelper(cc.resources))
    protected atlas: cc.SpriteAtlas[] = []
    protected eventCallback: Function;
    protected duration: number = 0.041;
    protected data: any
    private load: boolean = false;
    protected faceDir: DIR = DIR.LEFT;

    protected moveDir: DIR = DIR.LEFT;

    private static frameDataMap: TSMap<string, any> = new TSMap()

    private static atlasMap: TSMap<string, cc.SpriteFrame> = new TSMap()

    isLoad() {
        return this.load;
    }

    isVisible() {
        return this.node.opacity == 255;
    }
    setVisible(f: boolean) {
        if (f) {
            this.node.opacity = 255;
        } else {
            this.node.opacity = 0;
        }
    }

    setColor(r, g, b) {
        this.sprite.node.color = cc.color(r, g, b)
    }

    getFaceDir() {
        return this.faceDir;
    }

    setMoveDir(d: DIR) {
        this.moveDir = d;
    }
    getMoveDir() {
        return this.moveDir;
    }

    setOppositeDir() {
        let dir = this.faceDir == DIR.LEFT ? DIR.RIGHT : DIR.LEFT;
        this.setFaceDir(dir)
    }

    setFaceDir(d: DIR, initDir: DIR = DIR.LEFT) {
        this.faceDir = d;
        if (initDir == DIR.LEFT) {
            if (d == DIR.RIGHT) {
                this.sprite.node.scaleX = -1
            } else {
                this.sprite.node.scaleX = 1;
            }
        } else {
            if (d == DIR.RIGHT) {
                this.sprite.node.scaleX = 1
            } else {
                this.sprite.node.scaleX = -1;
            }
        }
        this.setMoveDir(d)
    }
    setEvent(callback: Function) {
        this.eventCallback = callback;
    }
    private loadCount: number = 0;
    private loadFrame: number = 0;

    protected playing: boolean = false;
    start() {
        this.load = true;
        // console.log(typeof this.config.json)
        // console.log('this.config.json  ',this.config.json.root)
        this.init();

    }

    clear() {
        this.config = null;
    }
    init() {
        if (this.config) {
            this.setData(this.config.json.root)
        } else {
            if (this.configName) {
                DragonAnimation.loader.loadRes('plist/' + this.configName, ResType.Json, (err, item: ResItem) => {
                    if (err) {
                        return;
                    }
                    this.setData(item.getRes().json.root)
                })
            }
        }

    }


    setData(root) {
        this.data = root;
        let list = this.data.animations.animation;
        if (list.length) {
            let count = list.length;
            for (let index = 0; index < count; index++) {
                const animation = list[index];
                DragonAnimation.frameDataMap.set(animation.name, animation)
            }
        } else {
            DragonAnimation.frameDataMap.set(list.name, list)
        }

        let plist = this.data.plists.plist;
        if (typeof plist == 'string') {
            this.loadCount = 1;
            this.loadAtlas(plist)

        } else {
            this.loadCount = plist.length;
            for (let index = 0; index < plist.length; index++) {
                const element: string = plist[index];
                this.loadAtlas(element)
            }
        }
    }

    loadAtlas(fileName: string) {
        // console.log('name ',fileName)
        let list = fileName.split('.')
        // console.log('list ',list)
        let url = 'plist/' + list[0]
        DragonAnimation.loader.loadRes(url, ResType.SpriteAtlas, (err, item: ResItem) => {
            if (err) {
                return;
            }
            this.atlas.push(item.getRes())
            this.loadFrame++;
            if (this.loadFrame >= this.loadCount) {
                if (this.actoinName) {
                    this.play(this.actoinName, this.loop)
                }

            }
        })
    }

    play(actionName: string = this.actoinName, loop: boolean = this.loop) {
        if (!this.data) {
            logWarn(' DragonAnimation play data is null actionName ',actionName,' isLoop ',loop)
            return;
        }
        this.loop = loop;
        this.actoinName = actionName
        this.frame = 0;
        this.dt = 0;
        this.frameData = DragonAnimation.frameDataMap.get(this.actoinName)
        // console.log(' list ',list)
        if (this.frameData) {
            this.playing = true;
            this.duration = this.frameData.delay;
            // console.log(' frameData ', this.frameData)
            this.updateFrame()
        } else {
            logError(' frameData is null actionName is ', actionName)
        }

    }

    // update(dt: number) {
    //     if (this.autoPlay) {
    //         if (!this.playing) {
    //             return;
    //         }
    //         this.updateObj(dt)
    //     }

    // }


    updateObj(dt: number) {
        // if (this.isPlaying) {
        // console.log(' udpate dt ', dt)
        this.dt += dt;
        if (this.dt >= this.duration) {
            this.dt = 0;
            this.updateFrame()
            return true;
        }
        // }
        return false;
    }

    updateFrame() {
        if (!this.frameData || this.atlas.length == 0) {
            // logWarn(' updateFrame error ')
            return;
        }
        let list = this.frameData.spriteFrame;
        if (typeof list == 'string') {

            if (this.frame == 0) {

                this.updateImage(list)
                this.frame++;
            } else {
                this.frame = 0;
                if (this.eventCallback) {
                    this.eventCallback(this)
                }
            }
            // logInfo('sfname ==================== ', sfname)

        } else {
            let frameCount: number = list.length
            if (this.frame < frameCount) {
                let sfname = list[this.frame]
                this.updateImage(sfname)
                this.frame++;
            } else {
                if (this.loop) {
                    this.frame = 0
                } else {
                    this.frame = list.length - 1;
                }
                let sfname = list[this.frame]
                this.updateImage(sfname)
                if (this.eventCallback) {
                    this.eventCallback(this)
                }

            }

        }
        // for (let index = 0; index < array.length; index++) {
        //     const element = array[index];

        // }
    }

    updateImage(spriteName: string) {

        let index = spriteName.indexOf('.')
        // logInfo('updateImage spriteName ==================== ', spriteName)
        if (index >= 0) {
            let sfname = spriteName.substring(0, index)
            if (DragonAnimation.atlasMap.has(sfname)) {
                this.sprite.spriteFrame = DragonAnimation.atlasMap.get(sfname)
                return;
            } else {
                for (let index = 0; index < this.atlas.length; index++) {
                    const element = this.atlas[index];
                    if (element.getSpriteFrame(sfname)) {
                        this.sprite.spriteFrame = element.getSpriteFrame(sfname)
                        DragonAnimation.atlasMap.set(sfname, element.getSpriteFrame(sfname))
                        return;
                    } else {
                        // console.warn(' updateImage null index ', index, ' sfName ', sfname)
                    }
                }
            }
            // console.error(' updateImage  error sfname ', sfname, ' configName ', this.configName, 'this.actoinName ' + this.actoinName, ' spriteName ', spriteName, this.frameData)
        } else {
            console.error('this.actoinName ' + this.actoinName, ' spriteName ', spriteName, this.frameData, ' this.frame ', this.frame)
        }




    }
}
